---
title: "POQ: ANES Analysis"
author: "Chloe Ahn"
author: "Diana C. Mutz"
output: html_document
urlcolor: blue
editor_options: 
  chunk_output_type: inline
---

```{r setup, include = FALSE}
knitr::opts_chunk$set(warning = FALSE, message = FALSE, echo = FALSE)
options(scipen = 0, digits = 12)
library('pacman')
pacman::p_load(foreign, ggplot2, dplyr, tidyr, tidyverse, gridExtra,
               car, haven, frequency, sjmisc, data.table, sjPlot,
               stargazer, margins, grid, questionr, rlang) 
```

***Loading the data***

All necessary SAV or CSV ANES files can be found in the Harvard Dataverse repository.

```{r anes_time_series}

# ANES Time Series Data

anes <- read_sav('anes_timeseries_cdf_spss_20220916.sav') %>%
  dplyr::rename(CaseId = VCF0006, year = VCF0004) %>%
  mutate(across(everything(), as.numeric)) %>%
  subset(year %in% c(1980, 1984, 1988, 1992, 1996, 2000, 2004, 2008, 2012, 2016, 2020)) %>%
  dplyr::select(CaseId, year,
                VCF0116,  # employment status
                VCF0104,  # gender
                VCF0106,  # race (3-category)
                VCF0301,  # party id
                VCF0110,  # education
                VCF0114,  # income
                VCF0101,  # age
                VCF0713,  # voting intention (pre-election)
                VCF9155,  # validated turnout
                VCF0706,  # self-reported turnout (post-election)
                VCF0717,  # influence others
                VCF0718,  # attend meeting
                VCF0719,  # work for party
                VCF0720,  # button or sticker
                VCF0721,  # donate
                VCF0218,  # ft value Democratic Party
                VCF0224,  # ft value Republican Party
                VCF0424,  # ft democratic presidential candidate
                VCF0426,  # ft republican presidential candidate
                VCF0310,  # political interest
                VCF9027,  # did you vote in the previous presidential election?
                VCF9154,  # voter file matching: validated voting
                VCF9088,  # dem candidate perceived ideology
                VCF9096   # rep candidate perceived ideology
  ) %>%
  mutate(
    VCF0116 = car::recode(VCF0116, "1=1; 2:8=0; else=NA"),  # employment
    VCF0104 = car::recode(VCF0104, "2=1; 1=0; else=NA"),    # gender
    VCF0106 = car::recode(VCF0106, "1=1; 2:3=0; else=NA"),   # race
    VCF0310 = car::recode(VCF0310, "1=3; 2=2; 3=1; else=NA"), # political interest
    VCF0713a = car::recode(VCF0713, "1=1; 2=1; 9=1; 4=0; else=NA"), # voting intention
    VCF0713b = car::recode(VCF0713, "1=1; 2=1; 3=0; 4=0; 9=1; else=NA"), # voting intention: alt
    TURNOUTpostinta = car::recode(VCF0706, "1=1; 2=1; 3=1; 4=1; 7=0; else=NA"), # post turnout
    TURNOUTpostintb = car::recode(VCF0706, "1=1; 2=1; 3=1; 4=1; 7=0; 0=0; else=NA"), # post turnout: alt
    TURNOUTpost = car::recode(VCF9155, "1=1; 3=0; 5=0; else=NA"), # validated
    votermatch = car::recode(VCF9154, '1=1; else=0'),
    TURNOUTlast = car::recode(VCF9027, '1=1; 2=1; 3=1; 5=1; 9=0; 0=0')
  ) %>%
  mutate(across(c(VCF0717, VCF0718, VCF0719, VCF0720, VCF0721), 
                ~car::recode(.x, "1=0; 2=1; else=NA"))) %>%
  rowwise() %>%
  # Sum the recoded values
  mutate(PARTICIPATION = rowSums(across(c(VCF0717, VCF0718, VCF0719, VCF0720, VCF0721)), na.rm = TRUE)) %>%
  # if all specific participation columns are NA, then the final participation should be NA
  mutate(PARTICIPATION = case_when(
    if_all(starts_with("VCF0717") | starts_with("VCF0718") |
           starts_with("VCF0719") | starts_with("VCF0720") |
           starts_with("VCF0721"), is.na) ~ NA_real_,
    TRUE ~ PARTICIPATION
  )) %>%
  ungroup() %>%
  # scaling the campaign participation variable to 0-1 range
  mutate(PARTICIPATION = (PARTICIPATION - min(PARTICIPATION, na.rm = T)) / 
                           (max(PARTICIPATION, na.rm = T) - min(PARTICIPATION, na.rm = T))) %>%
# only choose the relevant variables
  dplyr::select(
    CaseId, year, VCF0301,
    VCF0218, VCF0224, VCF0424, VCF0426, VCF0104, VCF0106,
    VCF0301, VCF0110, VCF0116, VCF0114, VCF0101, VCF0310,
    VCF0713a, VCF0713b, VCF9027, votermatch, VCF9088, VCF9096,
    TURNOUTlast, PARTICIPATION, TURNOUTpostinta, TURNOUTpostintb, TURNOUTpost) %>%
  mutate(year = as.numeric(year)) 

# 2020 post-election data

anes_2020_post <- fread('anes_timeseries_2020_csv_20220210.csv') %>%
  mutate(across(everything(), as.numeric)) %>%
  mutate(
    CaseId = V200001,
    year = 2020,
    votermatch = car::recode(V201008, '1=1; 2=1; else=0'),
    TURNOUTpostinta = case_when(V202072 == 1 ~ 1, V202072 == 2 ~ 0, V202072<0 ~ NA_real_),
    TURNOUTpostintb = TURNOUTpostinta
  ) %>%
  select(CaseId, votermatch, TURNOUTpostinta, TURNOUTpostintb) %>%
  distinct()

anes <-
  rbind(
    # non-2020 years
    anes |> filter(year!=2020),
    # 2020
    merge(anes_2020_post,
          anes |> filter(year==2020) |> select(-votermatch, -TURNOUTpostinta, -TURNOUTpostintb),
          by='CaseId', all=T)
  ) %>%
  distinct()

# 2012 voter validation file

valid2012 <- read.csv('anes_timeseries_2012voteval.csv', header = TRUE) %>%
  mutate(across(everything(), as.numeric)) %>%
  dplyr::rename(CaseId = caseid) %>%
  mutate(
    year = 2012,
    votermatch = car::recode(matched_respondent, '1=1; else=0'),
    TURNOUTpost = case_when(
      vendor1_2012g == 1 | vendor2_2012g == 1 | vendor3_2012g == 1 ~ 1,
      vendor1_2012g == 0 & vendor2_2012g == 0 & vendor3_2012g == 0 ~ 0,
      TRUE ~ NA_real_
    )
  ) %>%
  filter(CaseId > 0 & respondent == 1) %>%
  select(CaseId, TURNOUTpost, votermatch) %>%
  distinct()

anes <-
  rbind(
    # non-2012 years
    anes |> filter(year!=2012),
    # 2012
    merge(valid2012,
          anes |> filter(year==2012) |> select(-TURNOUTpost, -votermatch),
          by='CaseId', all=T)
  ) %>%
  distinct()

# 2016 voter validation file

valid2016 <- read.csv('anes_timeseries_2016_voteval.csv', header = TRUE) %>%
  mutate(across(everything(), as.numeric)) %>%
  mutate(
    V160001 = as.character(V160001),
    CaseId = as.numeric(substring(V160001, 3)),
    across(everything(), as.numeric), # Convert all columns to numeric
    year = 2016,
    votermatch = clerical_review, # Assign votermatch
    TURNOUTpost = case_when(vote2016 == 1 ~ 1, vote2016 == 0 ~ 0)
  ) %>%
  select(CaseId, TURNOUTpost, votermatch) %>%
  distinct()

anes <-
  rbind(
    # non-2016 years
    anes |> filter(year!=2016),
    # 2016
    merge(valid2016,
          anes |> filter(year==2016) |> select(-TURNOUTpost, -votermatch),
          by='CaseId', all=T)
  ) %>%
  distinct()

# Affective polarization
bin_values <- function(x) {
  case_when(
    x >= 0 & x <= 5 ~ 1,
    x > 5 & x <= 10 ~ 2,
    x > 10 & x <= 15 ~ 3,
    x > 15 & x <= 20 ~ 4,
    x > 20 & x <= 25 ~ 5,
    x > 25 & x <= 30 ~ 6,
    x > 30 & x <= 35 ~ 7,
    x > 35 & x <= 40 ~ 8,
    x > 40 & x <= 45 ~ 9,
    x > 45 & x <= 50 ~ 10,
    x > 50 & x <= 55 ~ 11,
    x > 55 & x <= 60 ~ 12,
    x > 60 & x <= 65 ~ 13,
    x > 65 & x <= 70 ~ 14,
    x > 70 & x <= 75 ~ 15,
    x > 75 & x <= 80 ~ 16,
    x > 80 & x <= 85 ~ 17,
    x > 85 & x <= 90 ~ 18,
    x > 90 & x <= 95 ~ 19,
    x > 95 & x <= 97 ~ 20,
    x >= 98 | x < 0 ~ NA_real_,
    TRUE ~ NA_real_
  )
}

# party based affective polarization
anes <- anes %>%
  mutate(
    VCF0218n = bin_values(VCF0218),
    VCF0224n = bin_values(VCF0224),
    AFFPOLpn = abs(VCF0218n - VCF0224n),
    AFFPOLpn_dem = VCF0218n,
    AFFPOLpn_rep = VCF0224n
  ) %>%
# candidate based affective polarization
  mutate(
    VCF0424n = bin_values(VCF0424),
    VCF0426n = bin_values(VCF0426),
    AFFPOLcn = abs(VCF0424n - VCF0426n),
    AFFPOLcn_dem = VCF0424n,
    AFFPOLcn_rep = VCF0426n
  )

anes <- anes %>%
  mutate(
    TURNOUTpreinta = VCF0713a,
    TURNOUTpreintb = VCF0713b,
    IDstrength = car::recode(VCF0301, "1=4; 2=3; 3=2; 4=1; 5=2; 6=3; 7=4; else=NA"),
    EDU = VCF0110,
    EMP = VCF0116,
    INC = VCF0114,
    GEN = VCF0104,
    RACE = VCF0106,
    VCF0101 = as.numeric(VCF0101),
    AGE = case_when(
      VCF0101 >= 17 & VCF0101 < 20 ~ 1,
      VCF0101 >= 20 & VCF0101 < 30 ~ 2,
      VCF0101 >= 30 & VCF0101 < 40 ~ 3,
      VCF0101 >= 40 & VCF0101 < 50 ~ 4,
      VCF0101 >= 50 & VCF0101 < 60 ~ 5,
      VCF0101 >= 60 & VCF0101 < 70 ~ 6,
      VCF0101 >= 70 & VCF0101 < 80 ~ 7,
      VCF0101 >= 80 ~ 8,
      TRUE ~ NA_real_
    ),
    POLINT = VCF0310
  ) %>%
  drop_na(year) %>%
  select(CaseId, TURNOUTpreinta, TURNOUTpreintb, TURNOUTpost, TURNOUTpostinta, TURNOUTpostintb,
         PARTICIPATION, AFFPOLpn, AFFPOLcn, AFFPOLpn_dem, AFFPOLpn_rep, AFFPOLcn_dem, AFFPOLcn_rep,
         TURNOUTlast, votermatch, IDstrength, POLINT, EDU, EMP, INC, AGE, GEN, RACE, year, VCF0301) %>%
  dplyr::rename(pid7 = VCF0301) %>%
  dplyr::rename(
    # outcome variables
    vote_intent = TURNOUTpreinta,
    post_turnout = TURNOUTpostinta,
    validated = TURNOUTpost,
    campaign = PARTICIPATION,
    # predictors
    aff_pol = AFFPOLpn,
    cand_therm = AFFPOLcn,
    id_strength = IDstrength,
    educ = EDU,
    employed = EMP,
    income = INC,
    age = AGE,
    female = GEN,
    white = RACE
  )

# Remove unnecessary files
rm(valid2012, valid2016, anes_2020_post)
```

***Figure 1***

```{r figure1}
range01 <- function(x){(x-min(x, na.rm = T))/(max(x, na.rm = T)-min(x, na.rm = T))}

figure1_labels <- c("Self-reported Pre-election Intent to Vote",
                    "Self-reported Post-election Turnout",
                    "Candidate Thermometer Difference",
                    "Affective Polarization",
                    "Campaign Participation")

anes |>
  group_by(year) |>
  dplyr::summarise(vote_intent = mean(vote_intent, na.rm = T),
                   post_turnout = mean(post_turnout, na.rm = T),
                   campaign = mean(campaign, na.rm=T),
                   aff_pol = mean(range01(aff_pol), na.rm = T),
                   cand_therm = mean(range01(cand_therm), na.rm = T)) |>
  reshape2::melt(
  id = "year",
  measure = c('vote_intent', 'post_turnout', 'cand_therm', 'aff_pol', 'campaign')) |>
  dplyr::mutate(variable = factor(variable,
  levels = c('vote_intent', 'post_turnout', 'cand_therm', 'aff_pol', 'campaign'))) |>
  ggplot(aes(x = year, y = value, col = variable, linetype = variable, size = variable)) +
  geom_line() +
  scale_size_manual(name = "Legend",
                    labels= figure1_labels,
                    values = c(0.6, 0.6, 1.0, 1.0, 0.6)) +
  scale_linetype_manual(name = "Legend",
                        values = c("dashed", "dotted", "solid", "solid", "dotdash"),
                        labels = figure1_labels) +
  scale_color_manual(name = "Legend",
                     values = c("black", "black", "grey75", "black", "black"),
                     labels = figure1_labels) +
  theme_minimal() +
    scale_y_continuous(
    name = "Intent to Vote / Post-election Turnout /\nCampaign Participation",
    sec.axis = sec_axis(~.*19,
                        name="Affective Polarization /\n Candidate Thermometer Difference",
                        breaks = c(0,19,4.75,9.5,14.25))) +
  xlab("Year") +
  expand_limits(y = 0)+
  theme(legend.title = element_blank())
#ggsave('figure1.pdf')
ggsave('poq_figure1.tiff',
       width = 7.29, height = 4.51, device='tiff', dpi=600)
```

Defining necessary functions and labels

```{r functions_labels}
# Variable Names and Labels
years <- c(
  'Aggregate', 1980, 1984, 1988, 1992, 1996,
  2000, 2004, 2008, 2012, 2016, 2020
)

years_validated <- c(
  'Aggregate', 1980, 1984, 1988, 2012, 2016
)

variable_names <- c(
  'Affective Polarization', 'Candidate Thermometer Difference',
  'Partisan Strength', 'Education', 'Employed', 'Income',
  'Age', 'Female', 'White', 'Constant'
)

figure2_3_5_labels <- c(
  "Aggregate", "Aggregate", "1980", "1980",
  "1984", "1984", "1988", "1988",
  "1992", "1992", "1996", "1996",
  "2000", "2000", "2004", "2004",
  "2008", "2008", "2012", "2012",
  "2016", "2016", "2020", "2020"
)

figure2_3_5_var <- rep(
  c('Affective Polarization', 'Candidate Thermometer Difference'), 12
)

figure4_labels <- c(
  "Aggregate", "Aggregate", "1980", "1980",
  "1984", "1984", "1988", "1988",
  "2012", "2012", "2016", "2016"
)

figure4_var <- rep(
  c('Affective Polarization', 'Candidate Thermometer Difference'), 6
)


# Functions

odds_ratio <- function(dv) {
  List <- list()
  
  for (i in 1:12) {
    if (i == 1) {
      List[[i]] <- as.data.frame(questionr::odds.ratio(
        glm(anes[[dv]] ~ aff_pol + cand_therm + id_strength + educ + employed +
            income + age + female + white + as.factor(year), 
            data = anes, family = binomial)
      )) |>
        slice(2:10) |>
        dplyr::mutate(year = 'Aggregate') |>
        tibble::rownames_to_column('variable')
      
    } else {
      anes_yearly <- anes |> filter(year == years[i])
      
      List[[i]] <- as.data.frame(questionr::odds.ratio(
        glm(anes_yearly[[dv]] ~ aff_pol + cand_therm + id_strength + educ + employed +
            income + age + female + white, 
            data = anes_yearly, family = binomial)
      )) |>
        slice(2:10) |>
        dplyr::mutate(year = years[i]) |>
        tibble::rownames_to_column('variable')
    }
  }
  
  df <- do.call(rbind, List) |>
    dplyr::rename(oddsratio = 2, low95 = 3, high95 = 4, pvalue = 5) |>
    dplyr::mutate(
      oddsratio = format(round(oddsratio, 3), nsmall = 3),
      low95 = format(round(low95, 3), nsmall = 3),
      high95 = format(round(high95, 3), nsmall = 3),
      pvalue = format(round(pvalue, 3), nsmall = 3)
    ) |>
    dplyr::filter(variable == 'aff_pol' | variable == 'cand_therm')
  
  return(df)
}


odds_ratio_validated <- function(dv) {
  List <- list()
  
  for (i in 1:6) {
    if (i == 1) {
      List[[i]] <- as.data.frame(questionr::odds.ratio(
        glm(anes[[dv]] ~ aff_pol + cand_therm + id_strength + educ + employed +
            income + age + female + white + as.factor(year), 
            data = anes, family = binomial)
      )) |>
        slice(2:10) |>
        dplyr::mutate(year = 'Aggregate') |>
        tibble::rownames_to_column('variable')
      
    } else {
      anes_yearly <- anes |> filter(year == years_validated[i])
      
      List[[i]] <- as.data.frame(questionr::odds.ratio(
        glm(anes_yearly[[dv]] ~ aff_pol + cand_therm + id_strength + educ + employed +
            income + age + female + white, 
            data = anes_yearly, family = binomial)
      )) |>
        slice(2:10) |>
        dplyr::mutate(year = years_validated[i]) |>
        tibble::rownames_to_column('variable')
    }
  }
  
  df <- do.call(rbind, List) |>
    dplyr::rename(oddsratio = 2, low95 = 3, high95 = 4, pvalue = 5) |>
    dplyr::mutate(
      oddsratio = format(round(oddsratio, 3), nsmall = 3),
      low95 = format(round(low95, 3), nsmall = 3),
      high95 = format(round(high95, 3), nsmall = 3),
      pvalue = format(round(pvalue, 3), nsmall = 3)
    ) |>
    dplyr::filter(variable == 'aff_pol' | variable == 'cand_therm')
  
  return(df)
}


ols_coef <- function(dv) {
  List <- list()
  ols_predict <- list()
  
  for (i in 1:12) {
    if (i == 1) {
      List[[i]] <- lm(anes[[dv]] ~ aff_pol + cand_therm + id_strength + educ + employed +
                      income + age + female + white + as.factor(year), data = anes)
      ols_predict[[i]] <- cbind(
        (as.data.frame(List[[i]]$coefficients) |> dplyr::rename(coef = 1)),
        (as.data.frame(sqrt(diag(vcov(List[[i]])))) |> dplyr::rename(se = 1))
      ) |>
        slice(2:3) |>
        dplyr::mutate(year = 'Aggregate') |>
        tibble::rownames_to_column('variable')
      
    } else {
      anes_yearly <- anes |> filter(year == years[i])
      List[[i]] <- lm(anes_yearly[[dv]] ~ aff_pol + cand_therm + id_strength + educ + employed +
                      income + age + female + white, data = anes_yearly)
      ols_predict[[i]] <- cbind(
        (as.data.frame(List[[i]]$coefficients) |> dplyr::rename(coef = 1)),
        (as.data.frame(sqrt(diag(vcov(List[[i]])))) |> dplyr::rename(se = 1))
      ) |>
        slice(2:3) |>
        dplyr::mutate(year = years[i]) |>
        tibble::rownames_to_column('variable')
    }
  }
  
  df <- do.call(rbind, ols_predict) |>
    dplyr::mutate(
      low95 = format(round((coef - se * 1.96), 7), nsmall = 7),
      high95 = format(round((coef + se * 1.96), 7), nsmall = 7),
      coef = format(round(coef, 7), nsmall = 7)
    ) |>
    dplyr::select(-se)
  
  return(df)
}

```

***DV1: Self-reported Pre-election Intent to Vote***

Figure 2

```{r figure2}
vote_intent_df <- odds_ratio(dv='vote_intent')
figure2_df <- data.frame(odds = as.numeric(c(vote_intent_df$oddsratio)),
                         ci_low = as.numeric(c(vote_intent_df$low95)),
                         ci_high = as.numeric(c(vote_intent_df$high95)),
                         labels = figure2_3_5_labels,
                         var = figure2_3_5_var)

figure2_df|>
    dplyr::mutate(
      var = factor(var,
      levels=c("Candidate Thermometer Difference", 'Affective Polarization'))) |>
    ggplot(aes(x = odds, y = labels)) +
    geom_vline(aes(xintercept = 1), size = .25, linetype = "dashed") + 
    geom_errorbarh(aes(xmax = ci_high, xmin = ci_low, color=var, group=var),
                   size = .5, height = 0, width = 0, position=position_dodge(width=.5)) +
    geom_point(aes(color=var), size = 3, pch=16, position=position_dodge(width=.5)) +
    coord_cartesian(xlim = c(0.9, 1.21), clip = 'off') +
    scale_x_continuous(breaks = (seq(0.9, 1.21, 0.1)),
                       limits = (c(0.9, 1.21))) +
    theme_minimal()+
    theme(panel.grid.minor = element_blank(),
          panel.grid.major = element_line(color = '#f2f2f2'),
          legend.position="top",
          text = element_text(size = 15)) +
    ylab("") + xlab("")+
    scale_color_manual(values=c('Affective Polarization'="#595959",
                                'Candidate Thermometer Difference'="#a6a6a6"),
                       breaks=c("Affective Polarization",
                                'Candidate Thermometer Difference'),
                       name='')
#ggsave('figure2.pdf', height = 7)
ggsave('poq_figure2.tiff',
       width = 7.29, height = 7, device='tiff', dpi=600)
```

***DV2: Self-reported Post-election Turnout***

Figure 3

```{r figure3}
post_turnout_df <- odds_ratio(dv='post_turnout')
figure3_df <- data.frame(odds = as.numeric(c(post_turnout_df$oddsratio)),
                         ci_low = as.numeric(c(post_turnout_df$low95)),
                         ci_high = as.numeric(c(post_turnout_df$high95)),
                         labels = figure2_3_5_labels,
                         var = figure2_3_5_var)

figure3_df|>
    dplyr::mutate(
      var = factor(var,
      levels=c("Candidate Thermometer Difference", 'Affective Polarization'))) |>
    ggplot(aes(x = odds, y = labels)) +
    geom_vline(aes(xintercept = 1), size = .25, linetype = "dashed") + 
    geom_errorbarh(aes(xmax = ci_high, xmin = ci_low, color=var, group=var),
                   size = .5, height = 0, width = 0, position=position_dodge(width=.5)) +
    geom_point(aes(color=var), size = 3, pch=16, position=position_dodge(width=.5)) +
    coord_cartesian(xlim = c(0.9, 1.2), clip = 'off') +
    scale_x_continuous(breaks = (seq(0.9, 1.2, 0.1)),
                       limits = (c(0.9, 1.2))) +
    theme_minimal()+
    theme(panel.grid.minor = element_blank(),
          panel.grid.major = element_line(color = '#f2f2f2'),
          legend.position="top",
          text = element_text(size = 15)) +
    ylab("") + xlab("")+
    scale_color_manual(values=c('Affective Polarization'="#595959",
                                'Candidate Thermometer Difference'="#a6a6a6"),
                       breaks=c("Affective Polarization",
                                'Candidate Thermometer Difference'),
                       name='')
#ggsave('figure3.pdf', height = 7)
ggsave('poq_figure3.tiff',
       width = 7.29, height = 7, device='tiff', dpi=600)
```

***DV3: Validated Turnout***

Figure 4

```{r figure4}
validated_df <- odds_ratio_validated(dv='validated')
figure4_df <- data.frame(odds = as.numeric(c(validated_df$oddsratio)),
                         ci_low = as.numeric(c(validated_df$low95)),
                         ci_high = as.numeric(c(validated_df$high95)),
                         labels = figure4_labels,
                         var = figure4_var)

figure4_df|>
    dplyr::mutate(
      var = factor(var,
      levels=c("Candidate Thermometer Difference", 'Affective Polarization'))) |>
    ggplot(aes(x = odds, y = labels)) +
    geom_vline(aes(xintercept = 1), size = .25, linetype = "dashed") + 
    geom_errorbarh(aes(xmax = ci_high, xmin = ci_low, color=var, group=var),
                   size = .5, height = 0, width = 0, position=position_dodge(width=.5)) +
    geom_point(aes(color=var), size = 3, pch=16, position=position_dodge(width=.5)) +
    coord_cartesian(xlim = c(0.9, 1.1), clip = 'off') +
    scale_x_continuous(breaks = (seq(0.9, 1.1, 0.1)),
                       limits = (c(0.9, 1.1))) +
    theme_minimal()+
    theme(panel.grid.minor = element_blank(),
          panel.grid.major = element_line(color = '#f2f2f2'),
          legend.position="top",
          text = element_text(size = 15)) +
    ylab("") + xlab("")+
    scale_color_manual(values=c('Affective Polarization'="#595959",
                                'Candidate Thermometer Difference'="#a6a6a6"),
                       breaks=c("Affective Polarization",
                                'Candidate Thermometer Difference'),
                       name='')
#ggsave('figure4.pdf', height = 7)
ggsave('poq_figure4.tiff',
       width = 7.29, height = 7, device='tiff', dpi=600)
```

***DV4: Campaign Participation***

Figure 5

```{r figure5}
campaign_df <- ols_coef(dv='campaign')
figure5_df <- data.frame(coef = as.numeric(c(campaign_df$coef)),
                         ci_low = as.numeric(c(campaign_df$low95)),
                         ci_high = as.numeric(c(campaign_df$high95)),
                         labels = figure2_3_5_labels,
                         var = figure2_3_5_var)

figure5_df|>
    dplyr::mutate(
      var = factor(var,
      levels=c("Candidate Thermometer Difference", 'Affective Polarization'))) |>
    ggplot(aes(x = coef, y = labels)) +
    geom_vline(aes(xintercept = 0), size = .25, linetype = "dashed") + 
    geom_errorbarh(aes(xmax = ci_high, xmin = ci_low, color=var, group=var),
                   size = .5, height = 0, width = 0, position=position_dodge(width=.7)) +
    geom_point(aes(color=var), size = 3, pch=16, position=position_dodge(width=.7)) +
    coord_cartesian(xlim = c(-0.0025, 0.0125), clip = 'off') +
    scale_x_continuous(breaks = (seq(-0.0025, 0.0125, 0.0025)),
                       limits = (c(-0.0025, 0.0125))) +
    theme_minimal()+
    theme(panel.grid.minor = element_blank(),
          panel.grid.major = element_line(color = '#f2f2f2'),
          legend.position="top",
          text = element_text(size = 15)) +
    ylab("") + xlab("")+
    scale_color_manual(values=c('Affective Polarization'="#595959",
                                'Candidate Thermometer Difference'="#a6a6a6"),
                       breaks=c("Affective Polarization",
                                'Candidate Thermometer Difference'),
                       name='')
#ggsave('figure5.pdf', height = 7)
ggsave('poq_figure5.tiff',
       width = 7.29, height = 7, device='tiff', dpi=600)
```
